package com.audaque.springboot.foshanupload.esdata.component;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONUtil;
import jodd.util.StringUtil;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zgb
 * @desc ...
 * @date 2023-06-14 19:35:29
 */
@Component
public class HighLevelClientProvider {

    @Autowired
    private RestHighLevelClient restHighLevelClient;
/*

    */
/**
     * 搜索并完成分页、高亮、排序
     *
     * @param req
     * @param beanClass
     * @return responseResult
     * @throws IOException
     *//*

    public <T> ResponseResult findObject(SearchReqDto req, Class<T> beanClass) throws IOException {
        if (ObjUtil.isNull(req) || StringUtil.isBlank(req.getIndices())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        if (StringUtil.isBlank(req.getOrderByColumn())) {
            req.setOrderByColumn("createdTime");
        }
        List<Object> resultList = null;
        Map<Object, Object> resultMap = new HashMap<>();
        SearchHits hits = queryBuilder(req);
        T bean = null;
        resultList = new ArrayList<>();
        //遍历查询结果并接收
        for (SearchHit searchHit : hits) {
            */
/**
             * 关键词为空或者没有高亮字段，不需要再处理
             *//*

            if (StringUtil.isBlank(req.getKeyword()) || ArrayUtil.isEmpty(req.getHighlightFields())) {
                bean = JSONUtil.toBean(searchHit.getSourceAsString(), beanClass);
            } else {
                bean = replaceAttr(searchHit, req.getHighlightFields(), beanClass);
            }
            if (ObjUtil.isNotNull(bean)) {
                resultList.add(bean);
            }
        }
        resultMap.put("total", resultList.size());
        resultMap.put("record", resultList);
        return ResponseResult.okResult(resultMap);
    }

    */
/**
     * 构造查询条件，获取原生返回数据
     *
     * @param req 查询条件
     * @return SearchHit
     * @throws IOException
     *//*

    public SearchHits queryBuilder(SearchReqDto req) throws IOException {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        HighlightBuilder highlightBuilder = new HighlightBuilder();

        int pageNum = req.getPageNum() > 0 ? req.getPageNum() : 1;
        int pageSize = req.getPageSize() > 0 ? req.getPageSize() : 10;
        //设置分页
        builder.from((pageNum - 1) * pageSize);
        builder.size(pageSize);

        //设置高亮
        highlightBuilder.field("*"); //所有的字段都高亮
        highlightBuilder.requireFieldMatch(false);//如果要多个字段高亮,这项要为false
        highlightBuilder.preTags("<font color='red'>").postTags("</font'>")
                .fragmentSize(800000)//下面这两项,如果你要高亮如文字内容等有很多字的字段,必须配置,不然会导致高亮不全,文章内容缺失等;  最大高亮分片数
                .numOfFragments(0);//从第一个分片获取高亮片段
        builder.highlighter(highlightBuilder);

        //模糊查询
        if (StringUtil.isBlank(req.getKeyword())) {
            boolQueryBuilder.should(QueryBuilders.matchAllQuery());
        } else {
            boolQueryBuilder.should(QueryBuilders.matchQuery("all", req.getKeyword()));
        }
        //对查询结果进行排序
        SortOrder order = SortOrder.ASC;
        if (SortOrder.DESC.name().equalsIgnoreCase(req.getIsAsc())) {
            order = SortOrder.DESC;
        }
        builder.query(boolQueryBuilder).sort(req.getOrderByColumn(), order);
        SearchRequest searchRequest = new SearchRequest(req.getIndices());
        searchRequest.source(builder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        return searchResponse.getHits();
    }
*/


    /**
     * 将高亮字段替换
     *
     * @param searchHit 查询结果
     * @param attrs     字段名
     * @return T
     */
    private <T> T replaceAttr(SearchHit searchHit, String[] attrs, Class<T> beanClass) {
        T bean = null;
        Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
        for (String field : attrs) {
            HighlightField hField = highlightFields.get(field);
            if (hField != null) {
                //替换高亮字段
                Text[] fragments = hField.fragments();
                StringBuilder text = new StringBuilder();
                for (Text textGet : fragments) {
                    text.append(textGet);
                }
                //对象的值只能读一次,否则会被覆盖
                if (bean!=null) {
                    //转换数据类型
                    bean = JSONUtil.toBean(searchHit.getSourceAsString(), beanClass);
                }
                //设置对象的属性值
                ReflectUtil.setFieldValue(bean, field, text.toString());
            }
        }
        return bean;
    }

}
